<?php

/**

 * 上传文件服务层

 * @author maniac

 */

namespace app\common\service;



use app\facade\Options AS OptionsFacade;
use app\common\model\Attaches;
use think\facade\Env;
require_once Env::get('ROOT_PATH')."vendor/aliyuncs/oss-sdk-php/src/OSS/OssClient.php";
require_once Env::get('ROOT_PATH')."vendor/topthink/think-image/src/Image.php";

use OSS\OssClient;
use app\common\service\ImageCrop;
use think\Image;

class Upload extends Base

{

    /**

     * 上传文件

     * @param  array $data 请求的信息

     */

    public function upload($data)

    {

        // 获取上传的文件信息

        $file = request()->file('imgFile');

        $info = $file->getInfo();
        $oss = false;
        if($oss){
            $result = $this->upload1($data,$info);
            return $result;
        }
        $thump = true;
        if($thump){
			$info['name'] = unid(16).'.jpg';
            $image = \think\Image::open(request()->file('imgFile'));
            $image->thumb(800, 800)->save('./static/uploads/thumb/'.$info['name']);
            $data['thumb_uri'] = '/static/uploads/thumb/'.$info['name'];
            $info["md5_file"]=md5_file($info['tmp_name']);

            $info["sha1_file"]=sha1_file($info['tmp_name']);

            $result = $this->compareFile($info, '/static/uploads/thumb/'.$info['name'], $data) ?: '/static/uploads/thumb/'.$info['name'];
        }else{

            // 获取系统设置信息

            $site = unserialize(Options::option('app_info'));

            $data['type'] = isset($data['type']) ? $data['type'] : $data['dir'];

            // 检测上传文件扩展名

            $this->checkFileExt($data['type'], $info, $site);

            // 检测上传文件大小

            $this->checkFileSize($data['type'], $info['size'], $site);



            // 指定上传路径

            $path = './static/uploads/'.$data['module'].'/'.$data['type'].'/'.$data['path'].'/'.date('Ymd', time()).'/';

            if (!is_dir($path)) {

                mkdir($path, 0755, true);

            }



            $info["md5_file"]=md5_file($info['tmp_name']);

            $info["sha1_file"]=sha1_file($info['tmp_name']);

            $file   = $file->move($path, md5_file($info['tmp_name']));

            $result = $this->compareFile($info, $path.$file->getFilename(), $data) ?: $path.$file->getFilename();
        }




        if ($file->getError()) {

            exception($file->getError());

        }




        return $result;

    }



    /**
     * 上传oss
     */
    public function upload1($data,$info)
    {

        $tmp = $info;

        //获取OSS 在config 内参数
        $oss_config = config('site.oss');

        //获取图片内容数组
        //用函数 对临时路径进行提取 对 图片名称进行处理
        $img = $this->disposeImg($tmp);
        if (!$img) {
            $return['status'] = 0;
            $return['info'] = '上传失败';
        }
        try {
            //实例化对象
            $ossClient = new OssClient($oss_config['accessKeyId'], $oss_config['accessKeySecret'], $oss_config['endpoint']);
            //上传
            $info = $ossClient->uploadFile($oss_config['bucket'], $img['file_name'], $img['path'])['info'];

        } catch (OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;
        }
        if ($info['http_code'] == '200') {
            $where     = [

                'module'    => $data['module'],

                'userid'    => $data['path'],

                'md5_file'  => $img['path'],

                'sha1_file' => $img['path'],

                'title'     => $tmp['tmp_name'],

                'attach_uri' => $info['url'],
                
                'type' => 1,

            ];


            $attach = Attaches::create($where);

            return ['id' => $attach->id, 'title' => $tmp['tmp_name'], 'attach_uri' => $info['url'], 'md5_file' => $img['path']];


        } else {
            $return['status'] = 0;
            $return['info'] = '上传失败';
        }
        return $return;
    }

    /**
     * 处理图片
     * @Author
     * @DateTime
     * @return    [json]      [图片url]
     */
    public function disposeImg($fileinfo)
    {
        if (!$fileinfo) {
            return false;
        }
        $scr = $fileinfo['tmp_name'];

        if(!empty($fileinfo['suffix'])){
            $arr=explode("/",$scr);
            $dst = 'chat/' . md5(time()) . '-' . $arr[5];     //上传文件名称
        }else{
            $ext = substr($fileinfo['name'], strrpos($fileinfo['name'], '.') + 1); // 上传文件后缀
            $dst = 'image/' . md5(time()) . '-' . $scr . '.' . $ext;     //上传文件名称
        }

        $data['file_name'] = $dst;
        $data['path'] = $scr;
        return $data;
    }
    

    /**

     * 附件管理

     * @param  array $data 请求的信息

     */

    public function filemanager($data)

    {

        $save_path = input('get.module') == 'manage' ? './static/uploads/manage/' : './static/uploads/public/';

        $sub_path  = input('get.sub_path', session('userid', '', session_prefix()));

        $path      = input('get.path');

        // 目录名

        $type      = empty($_GET['dir']) ? 'image' : trim($_GET['dir']);

        // 根目录路径，可以指定绝对路径。

        $root_path = $save_path.$type . '/'.$sub_path . '/';

        if (!in_array($type, ['image', 'file'])) {

            return [1, '非法的目录名'];

        }

        // 获取系统设置信息

        $site     = unserialize(OptionsFacade::option('app_info'));

        // 附件扩展名

        $allowExt = ['image' => $site['upload_image_filetype'], 'file' => $site['upload_attach_filetype']];

        $extArr   = explode('|', $allowExt[$type]);


        // 根据 path 参数，设置各路径和 url
        if (empty($_GET['path'])) {
            $current_path     = realpath($root_path) . '/';
            $current_url      = $current_path . input('get.path');
            $current_dir_path = '';
            $moveup_dir_path  = '';
        } else {

            $current_path     = realpath($root_path) . '/';

            $current_url      = $root_path . input('get.path');
            $current_dir_path = input('get.path');
            $moveup_dir_path  = preg_replace('/(.*?)[^\/]+\/$/', '$1', $current_dir_path);
        }
        
        // 排序方式，name/size/type
        $order = empty($_GET['order']) ? 'name' : strtolower($_GET['order']);
        // 不允许使用 .. 移动到上一级
        if (preg_match('/\.\./', $current_path)) {
            return [2, '不允许访问上级目录'];
        }
        // 最后一个字符不是 /
        if (!preg_match('/\/$/', $current_path)) {
            return [3, '分隔符不合法'];
        }
        // 目录不存在或不是目录
        if (!file_exists($current_path) || !is_dir($current_path)) {
            return [4, '目录不存在'];
        }
        
        // 遍历目录得到文件信息
        $file_list = [];
        if ($handle = opendir($current_path)) {
            $i = 0;
            while (false !== ($filename = readdir($handle))) {
                if ($filename{0} == '.') continue;
                $file = $current_path . $filename;
                if (is_dir($file)) {
                    $file_list[$i]['is_dir']   = true;    // 是否是目录
                    $file_list[$i]['has_file'] = (count(scandir($file)) > 2);   // 目录中是否包含文件
                    $file_list[$i]['filesize'] = 0; // 文件大小
                    $file_list[$i]['is_photo'] = false; // 是否图片
                    $file_list[$i]['filetype'] = '';    // 文件类别，用扩展名判断
                } else {
                    $file_list[$i]['is_dir']   = false;
                    $file_list[$i]['has_file'] = false;
        			$file_list[$i]['filesize'] = filesize($file);
        			$file_list[$i]['dir_path'] = '';
        			$file_ext                  = strtolower(pathinfo($file, PATHINFO_EXTENSION));
        			$file_list[$i]['is_photo'] = in_array('.'.$file_ext, $extArr);
        			$file_list[$i]['filetype'] = $file_ext;
                    
                }
        		$file_list[$i]['filename'] = $filename; //文件名，包含扩展名
        		$file_list[$i]['datetime'] = date('Y-m-d H:i:s', filemtime($file)); //文件最后修改时间
        		$i++;
            }
        	closedir($handle);
        }
        usort($file_list, 'cmp_func');

        $result = [
            'moveup_dir_path'  => $moveup_dir_path,                      //相对于根目录的上一级目录
            'current_dir_path' => $current_dir_path,                     //相对于根目录的当前目录
            'current_url'      => str_replace('./', '/', $current_url),  //当前目录的URL
            'total_count'      => count($file_list),                     //文件数
            'file_list'        => $file_list,                            //文件列表数组
        ];
        return $result;
    }
    
    /**
     * 检测上传文件扩展名
     * @param  string $type 上传文件的类型
     * @param  array  $info 上传的文件信息
     * @param  array  $site 系统设置信息
     */
    private function checkFileExt($type, $info, $site)
    {
        // 获取文件扩展名
        $ext  = substr($info['name'], strrpos($info['name'], '.'));
        $allowExt = ['image' => $site['upload_image_filetype'], 'file' => $site['upload_attach_filetype']];
        $extArr   = explode('|', $allowExt[$type]);
        if (!in_array($ext, $extArr)) {
            exception('您上传的文件类型不合法，允许的类型：'.$allowExt[$type]);
        }
        return true;
    }
    
    /**
     * 检测上传文件大小
     * @param  string $type 上传文件的类型
     * @param  string $size 上传文件的大小
     * @param  array  $site 系统设置信息
     */
    private function checkFileSize($type, $size, $site)
    {
        $maxSize = ['image' => $site['upload_image_filesize'], 'file' => $site['upload_attach_filesize']];

        if ($size > $maxSize[$type]*1024) {
            exception('您上传的文件大小超出系统限制：'.transfer_size($maxSize[$type]));
        }
        return true;
    }
    
    /**
     * 对比文件的 MD5 散列值，sha1 散列值
     * @param  array  $info     上传的文件信息
     * @param  string $filename 上传的文件
     * @param  array  $data     请求的信息
     */
    private function compareFile($info, $filename, $data)
    {
        $md5_file  = $info["md5_file"];//md5_file($info['tmp_name']);
        $sha1_file = $info["sha1_file"];//sha1_file($info['tmp_name']);
        $where     = [
            'module'    => $data['module'],
            'userid'    => $data['path'],
            'md5_file'  => $md5_file,
            'sha1_file' => $sha1_file,
        ];

//        $attach = Attaches::field('id,title,attach_uri,md5_file')->where($where)->find();
//
//
//
//        if ($attach) {
//
//            return $attach;
//
//        }

        $where['title']      = $info['name'];
        $where['attach_uri'] = trim($filename, '.');
        $attach = Attaches::create($where);
        return ['id' => $attach->id, 'title' => $info['name'], 'attach_uri' => config('system.attach_uri_prefix').ltrim($where['attach_uri'], '/'), 'md5_file' => $md5_file];
    }
}
